package com.scorpio.goods.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.github.pagehelper.PageInfo;
import com.scorpio.basic.domain.OssDatumEntity;
import com.scorpio.basic.dto.NameIdDTO;
import com.scorpio.basic.dto.OssDatumDTO;
import com.scorpio.basic.enums.GoodsImageTypeEnum;
import com.scorpio.basic.service.OssDatumService;
import com.scorpio.basic.vo.OssDatumVo;
import com.scorpio.common.constant.HttpStatus;
import com.scorpio.common.core.page.TableDataInfo;
import com.scorpio.common.exception.CustomException;
import com.scorpio.common.utils.ConvertUtils;
import com.scorpio.goods.domain.GoodsCategoryEntity;
import com.scorpio.goods.domain.GoodsSkuEntity;
import com.scorpio.goods.dto.GoodsDTO;
import com.scorpio.goods.service.IGoodsCategoryService;
import com.scorpio.goods.service.IGoodsSkuService;
import com.scorpio.goods.service.IGoodsSkuSpecService;
import com.scorpio.goods.vo.AddGoodsSkuGroupVo;
import com.scorpio.goods.vo.AddGoodsVo;
import com.scorpio.goods.vo.UpdateInventoryVo;
import com.scorpio.redis.cachelock.RedisLock;
import com.scorpio.redis.cachelock.RedisLockException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.scorpio.goods.mapper.GoodsMapper;
import com.scorpio.goods.domain.GoodsEntity;
import com.scorpio.goods.service.IGoodsService;
import com.scorpio.common.service.impl.BaseServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 商品Service业务层处理
 *
 * @author scorpio
 * @date 2021-10-29
 */
@Service
public class GoodsServiceImpl extends BaseServiceImpl<GoodsMapper, GoodsEntity> implements IGoodsService {

    @Autowired
    private RedisLock redisLock;

    @Autowired
    private OssDatumService ossDatumService;

    @Autowired
    private IGoodsSkuService goodsSkuGroupService;

    @Autowired
    private IGoodsCategoryService categoryService;

    @Autowired
    private IGoodsSkuSpecService skuSpecService;

    //查询
    @Override
    public GoodsEntity selectById(Long id) {
        GoodsDTO entity = ConvertUtils.sourceToTarget(baseDao.getById(id), GoodsDTO.class);
        setGoodsDetails(entity);
        return entity;
    }

    //查询列表
    @Override
    public TableDataInfo selectList(GoodsEntity entity) {
        List<GoodsEntity> list = baseDao.list(entity);
        List<GoodsDTO> dtos = ConvertUtils.sourceToTarget(list, GoodsDTO.class);
        for (GoodsDTO dto : dtos) {
            dto.setImages(ossDatumService.selectImages(GoodsImageTypeEnum.Image.getType(), dto.getId()));
        }
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setTotal(new PageInfo(list).getTotal());
        rspData.setRows(dtos);
        return rspData;
    }

    @Override
    public int updateSoldoutAndPrice(Long id) {
        return baseDao.updateSoldoutAndPrice(id);
    }

    private void setGoodsDetails(GoodsDTO dto) {
        if (dto == null) return;
        List<OssDatumDTO> imageOss = ossDatumService.selectList(GoodsImageTypeEnum.Image.getType(), dto.getId());
        List<OssDatumDTO> detailsOss = ossDatumService.selectList(GoodsImageTypeEnum.Details.getType(), dto.getId());
        dto.setImageOss(imageOss);
        dto.setDetailsOss(detailsOss);
        dto.setSkuGroup(ConvertUtils.sourceToTarget(goodsSkuGroupService.selectByGoods(dto.getId()), NameIdDTO.class));
    }

    //新增
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int save(AddGoodsVo vo) {
        String lockKey = "";
        if (redisLock.lock(lockKey, 5)) {
            try {
                GoodsCategoryEntity categoryEntity = categoryService.selectById(vo.getCategoryId());
                if (categoryEntity == null || categoryEntity.getLevel() != 2) {
                    throw new CustomException("无效类目");
                }
                GoodsEntity entity = ConvertUtils.sourceToTarget(vo, GoodsEntity.class);
                int count = baseDao.insert(entity);
                if (count == 0) {
                    throw new CustomException("操作失败");
                }
                List<OssDatumVo> imageOss = vo.getImageOss();
                List<OssDatumVo> detailsOss = vo.getDetailsOss();
                List<AddGoodsSkuGroupVo> goodsSku = vo.getSkuGroup();
                for (int i = 0; i < imageOss.size(); i++) {
                    OssDatumVo oss = imageOss.get(i);
                    ossDatumService.save(GoodsImageTypeEnum.Image.getType(), entity.getId(), oss.getImage(), imageOss.size() - i);
                }

                for (int i = 0; i < detailsOss.size(); i++) {
                    OssDatumVo oss = detailsOss.get(i);
                    ossDatumService.save(GoodsImageTypeEnum.Details.getType(), entity.getId(), oss.getImage(), detailsOss.size() - i);
                }

                for (int i = 0; i < goodsSku.size(); i++) {
                    AddGoodsSkuGroupVo groupVo = goodsSku.get(i);
                    GoodsSkuEntity skuGroup = new GoodsSkuEntity();
                    skuGroup.setGoodsId(entity.getId());
                    skuGroup.setName(groupVo.getName());
                    skuGroup.setSort(goodsSku.size() - i);
                    if (goodsSkuGroupService.save(skuGroup) == 0) {
                        throw new CustomException("操作失败");
                    }
                }
                Long number = 1000000l + entity.getId();
                baseDao.updateGoodsNumber(entity.getId(), "" + number);
                return count;
            } finally {
                redisLock.unlock(lockKey);
            }
        }
        throw new RedisLockException();
    }

    //修改$
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(AddGoodsVo vo) {
        String lockKey = "GoodsServiceImpl_update:" + vo.getId();
        if (redisLock.lock(lockKey, 5)) {
            try {
                GoodsCategoryEntity categoryEntity = categoryService.selectById(vo.getCategoryId());
                if (categoryEntity == null || categoryEntity.getLevel() != 2) {
                    throw new CustomException("无效类目");
                }
                int count = baseDao.updateById(ConvertUtils.sourceToTarget(vo, GoodsEntity.class));
                if (count > 0) {
                    List<OssDatumVo> imageOss = vo.getImageOss();
                    List<OssDatumVo> detailsOss = vo.getDetailsOss();
                    List<Long> newIds = new ArrayList<>();
                    for (int i = 0; i < imageOss.size(); i++) {
                        OssDatumVo oss = imageOss.get(i);
                        if (oss.getId() != null) {
                            ossDatumService.updateSort(oss.getId(), imageOss.size() - i);
                            newIds.add(oss.getId());
                        } else {
                            OssDatumEntity entity = ossDatumService.save(GoodsImageTypeEnum.Image.getType(), vo.getId(), oss.getImage(), imageOss.size() - i);
                            newIds.add(entity.getId());
                        }
                    }
                    ossDatumService.updateDeleteNotContain(GoodsImageTypeEnum.Image.getType(), vo.getId(), newIds);
                    newIds.clear();

                    for (int i = 0; i < detailsOss.size(); i++) {
                        OssDatumVo oss = detailsOss.get(i);
                        if (oss.getId() != null) {
                            ossDatumService.updateSort(oss.getId(), detailsOss.size() - i);
                            newIds.add(oss.getId());
                        } else {
                            OssDatumEntity entity = ossDatumService.save(GoodsImageTypeEnum.Details.getType(), vo.getId(), oss.getImage(), detailsOss.size() - i);
                            newIds.add(entity.getId());
                        }
                    }
                    ossDatumService.updateDeleteNotContain(GoodsImageTypeEnum.Details.getType(), vo.getId(), newIds);
                    updateSoldoutAndPrice(vo.getId());
                }
                return count;
            } finally {
                redisLock.unlock(lockKey);
            }
        }
        throw new RedisLockException();
    }

    //批量删除$
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteByIds(Long[] ids) {
        return baseDao.updateDelete(ids);
    }

    @Override
    public int updateInventory(Long id, Integer change) {
        return baseDao.updateInventory(id, change);
    }
}
